#!/usr/bin/env python

# bt_adapter.py - A pygtk2 application to demonstrate bluetooth functions
#
# Version 0.1
#
# Authors: Erin Yueh <erinyueh@gmail.com>
#
# Copyright (c) 2008 Erin Yueh
#
# bt_adapter.py is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 3 of the License, or (at your
# option) any later version.
#
# browse_device.py is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.

import gtk, gobject
import browse_device

import dbus
from dbus.mainloop.glib import DBusGMainLoop
DBusGMainLoop(set_as_default=True)
bus = dbus.SystemBus()


class BluetoothAdapter(object):

    def __init__(self,bt):

        self.bt_main = bt

        self.btObj = bus.get_object( "org.freesmartphone.odeviced", "/org/freesmartphone/Device/PowerControl/Bluetooth")
        self.btInf = dbus.Interface( self.btObj, "org.freesmartphone.Device.PowerControl" )
        if self.btInf.GetPower() == 0:
            self.btInf.SetPower(True)
        self.managerObj = bus.get_object('org.bluez', '/org/bluez')
        self.managerInf = dbus.Interface(self.managerObj, 'org.bluez.Manager')
        # /org/bluez/hci0
        self.defaultadapter = self.managerInf.DefaultAdapter()

        #self.adapterObj = bus.get_object('org.bluez', self.managerInf.DefaultAdapter())
        self.adapterObj = bus.get_object('org.bluez', '/org/bluez/hci0')
        self.adapterInf = dbus.Interface(self.adapterObj, 'org.bluez.Adapter')

        bus.add_signal_receiver(self.bonding_created_signal, 'BondingCreated', 'org.bluez.Adapter', 'org.bluez', self.defaultadapter)
        bus.add_signal_receiver(self.bonding_removed_signal, 'BondingRemoved', 'org.bluez.Adapter', 'org.bluez', self.defaultadapter)
        
        bus.add_signal_receiver(self.disc_started_signal, 'DiscoveryStarted', 'org.bluez.Adapter', 'org.bluez', self.defaultadapter)
        bus.add_signal_receiver(self.disc_completed_signal, 'DiscoveryCompleted', 'org.bluez.Adapter', 'org.bluez', self.defaultadapter)
        
        bus.add_signal_receiver(self.rem_dev_connected_signal, 'RemoteDeviceConnected', 'org.bluez.Adapter', 'org.bluez', self.defaultadapter)
        bus.add_signal_receiver(self.rem_dev_disconnected_signal, 'RemoteDeviceDisconnected', 'org.bluez.Adapter', 'org.bluez', self.defaultadapter)
        
        
        bus.add_signal_receiver(self.rem_dev_found_signal, 'RemoteDeviceFound', 'org.bluez.Adapter', 'org.bluez', self.defaultadapter)
        bus.add_signal_receiver(self.rem_dev_disappeared_signal, 'RemoteDeviceDisappeared', 'org.bluez.Adapter', 'org.bluez', self.defaultadapter)
        bus.add_signal_receiver(self.rem_dev_name_signal, 'RemoteNameUpdated', 'org.bluez.Adapter', 'org.bluez', self.defaultadapter)

        bus.add_signal_receiver(self.mode_changed_signal, 'ModeChanged', 'org.bluez.Adapter', 'org.bluez', self.defaultadapter)

        self.device_list = {}

    def retrieve_names_fromFile(self):
        # read last seen devices
        adapter_address = self.getAddress()
        self.fname = "/var/lib/bluetooth/"+adapter_address+"/names"
        self.lastseen = []
        try:
            self.f = open(self.fname, 'r')
            for line in self.f:
                self.lastseen.append(line[0:17])
            self.f.close()
        except Exception:
            print 'cannot find this file', self.fname
        return self.lastseen

    def bonding_created_signal(self,address):
        # send a callback to browse device 
        self.bt_main.browse.bonding_created_cb(address)
        print 'Signal: BondingCreated(%s)' % address

    def bonding_removed_signal(self,address):
        # send a callback to browse device 
        self.bt_main.browse.bonding_removed_cb(address)
        print 'Signal: BondingRemoved(%s)' % address

    def disc_started_signal(self,):
        print 'Signal: DiscoveryStarted()'
        
    def disc_completed_signal(self):
        print 'Signal: DiscoveryCompleted()'

    def rem_dev_disappeared_signal(self, address):
        print 'Signal: RemoteDeviceDisappeared()', address
        if address in self.device_list:
            self.device_list.pop(address)
        
    def rem_dev_found_signal(self,address, cls, rssi):
        #print 'Signal: RemoteDeviceFound(%s, %s, %s)' % (address, cls, rssi)
        name = self.adapterInf.GetRemoteName(address)
        _type = self.adapterInf.GetRemoteMajorClass(address)
        security = self.getPinCodeLength(address)
        self.device_list[address] = (name,_type,security)
        
    def rem_dev_name_signal(self,address, name):
        print 'Signal: RemoteNameUpdated(%s, %s)' % (address, name)

    def rem_dev_connected_signal(self,address):
        print 'Signal: RemoteDeviceConnected(%s)' % address

    def rem_dev_disconnected_signal(self,address):
        print 'Signal: RemoteDeviceDisconnected(%s)' % address
        
    def mode_changed_signal(self,mode):
        print 'Signal: ModeChanged(%s)' % mode

    def getPower(self):
        
        return self.btInf.GetPower()
        try:
            self.btPower = self.btInf.GetPower()
            return self.btPower
        except Exception:
            print 'getPower error'
            return None

    def setPower(self,status):
        try:
            self.btInf.SetPower(status)
        except Exception:
            print 'setPower error', status

    def getInfo(self):
        try:
            self.Info = self.adapterInf.GetInfo()
            return self.Info
        except Exception:
            print 'getInfo error'
            return None

    def getAddress(self):
        try:
            self.Address = self.adapterInf.GetAddress()
            return self.Address
        except Exception:
            print 'getAddress error'
            return None
        
    def getName(self):
        try:
            self.Name = self.adapterInf.GetName()
            return self.Name
        except Exception:
            print 'getName error'
            return None

    def getMode(self):
        try:
            self.Mode = self.adapterInf.GetMode()
            return self.Mode
        except Exception:
            print 'getMode error'
            return None
            
    def getMajorClass(self):
        try:
            self.MajorClass = self.adapterInf.GetMajorClass()
            return self.MajorClass
        except Exception:
            print 'getMajorClass error'
            return None        

    def setName(self,name):
        try:
            self.adapterInf.SetName(str(name))
        except Exception:
            print 'setName error', name

    def setMode(self,mode):
        try:
            self.adapterInf.SetMode(str(mode))
        except Exception:
            print 'setMode error', Mode

    def getDiscoverableTimeout(self):
        try:
            self.DiscoverableTimeout = self.adapterInf.GetDiscoverableTimeout()
            return self.DiscoverableTimeout
        except Exception:
            print 'getDiscoverableTimeout error'
            return None        
        
    def setDiscoverableTimeout(self,second):
        try:
            self.adapterInf.SetDiscoverableTimeout(second)
        except Exception:
            print 'setDiscoverableTimeout error', second

    def getServiceClasses(self):
        try:
            self.ServiceClasses = self.adapterInf.GetServiceClasses()
            return self.ServiceClasses
        except Exception:
            print 'getServiceClasses error'
            return None  

    def listBondings(self):
        
        return self.adapterInf.ListBondings()

    def listConnections(self):
        
        return self.adapterInf.ListConnections()
    
    def hasBonding(self,addr):
        try:
            self.bond = self.adapterInf.HasBonding(addr)
            return self.bond
        except dbus.exceptions.DBusException,e:
            print 'hasBonding error: ',addr,e        
            return None

    def createBonding(self,addr):
        print 'createBonding', addr
        try:
            self.adapterInf.CreateBonding(addr)
        except dbus.exceptions.DBusException,e:
            print 'createBonding error: ',addr,e

    def removeBonding(self,addr):
        try:
            self.adapterInf.RemoveBonding(addr)
        except dbus.exceptions.DBusException,e:
            print 'removeBonding error: ',addr,e
            
    def getPinCodeLength(self,addr):
        try:
            self.PinCodeLength = self.adapterInf.GetPinCodeLength(addr)
            return self.PinCodeLength
        except Exception:
            return 0

    def setTrusted(self,addr):
        try:
            self.adapterInf.SetTrusted(addr)
        except Exception:
            print 'setTrusted error', addr

    def isTrusted(self,addr):
        try:
            self.isTrusted = self.adapterInf.IsTrusted(addr)
            return self.isTrusted
        except dbus.exceptions.DBusException,e:
            print 'isTrusted error: ',addr,e        
            return None
            
    def removeTrust(self,addr):
        try:
            self.adapterInf.RemoveTrust(addr)
        except Exception:
            print 'removeTrust error', addr
            
    def getEncryptionKeySize(self,addr):
        try:
            self.EncryptionKeySize = self.adapterInf.GetEncryptionKeySize(addr)
            return self.EncryptionKeySize
        except Exception:
            return None

    def listTrusts(self):
        
        return self.adapterInf.ListTrusts()

    def getRemoteInfo(self,addr):
        try:
            self.RemoteInfo = self.adapterInf.GetRemoteInfo(addr)
            return self.RemoteInfo
        except dbus.exceptions.DBusException,e:
            print 'getRemoteInfo: ',addr,e
            return None
    
    def getRemoteClass(self,addr):
        try:
            self.RemoteClass = self.adapterInf.GetRemoteClass(addr)
            return self.RemoteClass
        except dbus.exceptions.DBusException,e:
            print 'getRemoteClass: ',addr,e
            return None
            
    def getRemoteName(self,addr):
        try:
            self.RemoteName = self.adapterInf.GetRemoteName(addr)
            return self.RemoteName
        except dbus.exceptions.DBusException,e:
            print 'getRemoteName: ',addr,e
            return None


    def getRemoteMajorClass(self,addr):
        try:
            self.RemoteMajorClass = self.adapterInf.GetRemoteMajorClass(addr)
            return self.RemoteMajorClass
        except dbus.exceptions.DBusException,e:
            print 'getRemoteMajorClass: ',addr,e
            return None
            
    def getRemoteServiceClasses(self,addr):
        try:
            self.RemoteServiceClasses = self.adapterInf.GetRemoteServiceClasses(addr)
            return self.RemoteServiceClasses
        except dbus.exceptions.DBusException,e:
            print 'GetRemoteServiceClasses: ',addr,e
            return None
            
    def getRemoteServiceHandles(self,addr,match):
        try:
            print 'getRemoteServiceHandles',addr,match
            self.RemoteServiceHandles = self.adapterInf.GetRemoteServiceHandles(addr,match)
            return self.RemoteServiceHandles
        except dbus.exceptions.DBusException,e:
            print 'getRemoteServiceHandles: ',addr,match,e
            return None

    def getRemoteServiceRecord(self,addr,handle):
        try:
            self.RemoteServiceRecord = self.adapterInf.GetRemoteServiceRecord(addr,handle)
            return self.RemoteServiceRecord
        except dbus.exceptions.DBusException,e:
            print 'getRemoteServiceRecordAsXML: ',addr,handle,e
            return None

    def getRemoteServiceRecordAsXML(self,addr,handle):
        try:
            self.RemoteServiceRecordAsXML = self.adapterInf.GetRemoteServiceRecordAsXML(addr,handle)
            return self.RemoteServiceRecordAsXML
        except dbus.exceptions.DBusException,e:
            print 'getRemoteServiceRecordAsXML: ',addr,handle,e
            return None


    def listRemoteDevices(self):
        try:
            self.ListRemoteDevices = self.adapterInf.ListRemoteDevices()
            return self.ListRemoteDevices
        except dbus.exceptions.DBusException,e:
            print 'ListRemoteDevices: ',e
            return None

    def discoverDevices(self):
        try:
            self.ListRemoteDevices = self.adapterInf.DiscoverDevices()
        except dbus.exceptions.DBusException,e:
            print 'discoverDevices: ',e
